#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFileDialog>
#include <QPixmap>
#include <QLabel>
#include <QMessageBox>
#include <QAction>
#include <QMenu>
#include <QDialog>
#include <QDir>
#include <QFile>
#include <QDesktopWidget>
#include <QApplication>

#include <sstream>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_pLogger(new Logger("IRIS_Recognition.log"))
{
    ui->setupUi(this);

    QDesktopWidget* desktop = QApplication::desktop(); // =qApp->desktop()
    move((desktop->width() - this->width())/2,
         (desktop->height() - this->height())/2);

//    setCentralWidget(this);

    QDir dir ("..");
    m_rootPath = dir.absolutePath();
    if(! dir.exists())
    {
        m_rootPath = ".";
        qWarning() << "Directory .. is not exists";
    }
    qDebug() << "rootPath:" << m_rootPath;

    initMenu();
    initComBox();

    m_pDB.reset(new DataBase());
    m_pDB->initDriver();
//    m_pDB->initDbAndTable();

    ui->labShow->clear();

    m_iIsGetChara = false;
    m_iIsComparing = false;
    m_iIsLeftSelected = false;
//    m_iIsRightSelected = false;
    m_leftPictureName = "";
//    m_rightPictureName = "";

    m_allSteps = 5;
    m_curStepAll = 0;
//    KNN tN(3);
    qDebug() << "Init Successful";
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initMenu()
{
    //add file menu
//    QAction* pLeftOpen = new QAction(tr("openSourcePicture"),this);
    QAction* pLeftOpen = new QAction(tr("源图"),this);
    pLeftOpen->setShortcuts(QKeySequence::Open);
    pLeftOpen->setStatusTip(tr("Open an existing picture(*.bmp)"));
    connect(pLeftOpen, &QAction::triggered,
            this, &MainWindow::on_btnLeftOpenPicture_clicked);

//    QAction * openRightAction = new QAction(tr("openTargetPicture"), this);
//    QAction * openRightAction = new QAction(tr("目标"), this);
//    openRightAction->setShortcuts(QKeySequence::Copy);
//    openRightAction->setStatusTip(tr("Open an existing picture(*.bmp)"));
//    connect(openRightAction, &QAction::triggered,
//            this, &MainWindow::on_btnRightOpenPicture_clicked);

    QAction * pCloseAction = new QAction(tr("关闭"), this);
    pCloseAction->setShortcuts(QKeySequence::Close);
    pCloseAction->setStatusTip(tr("Close and quit software"));
    connect(pCloseAction, &QAction::triggered,
            this, &MainWindow::on_btnQuit_clicked);

    QMenu *pMenu = ui->menuBar->addMenu(tr("文件"));
    pMenu->addAction(pLeftOpen);
//    pMenu->addAction(openRightAction);
    pMenu->addAction(pCloseAction);

    //add operator menu
//    QAction * pSaveCharaAction = new QAction(tr("直接入库"), this);
//    connect(pSaveCharaAction, &QAction::triggered,
//            this, &MainWindow::directSaveChara);

//    QMenu *pOperatorMenu = ui->menuBar->addMenu(tr("编辑"));
//    pOperatorMenu->addAction(pSaveCharaAction);

    //add help menu
    QAction * pAboutAction = new QAction(tr("关于"), this);
    pAboutAction->setStatusTip(tr("Look up detail of the software"));
    connect(pAboutAction, &QAction::triggered,
            this, &MainWindow::slotAbout);

    QMenu *pHelpMenu = ui->menuBar->addMenu(tr("帮助"));
    pHelpMenu->addAction(pAboutAction);
}

void MainWindow::initComBox()
{
    //    ui->cbxSelect->addItem(tr("PHT"));
}

void MainWindow::directSaveChara()
{
    if(m_iIsComparing)
    {
        return;
    }
    if( ! m_iIsLeftSelected)
    {
        qWarning() << "Ensure source is selected right";
        QMessageBox::warning(
                    this,
                    tr("警告"),
                    tr("请确认源图片已选择!"),
                    QMessageBox::Ok);
        return;
    }
    m_iIsComparing = true;
    ui->labShow->setText("Saving . . .");

    BMPFile bmpFile (m_rootPath + "/" +m_leftPictureName);
    CharacterVector arrCharactor[CHARACTER_LENGTH];
    if( !bmpFile.getCharactor(arrCharactor,CHARACTER_LENGTH))
    {
        ui->labShow->setText(tr("失败"));
        return;
    }
    int xuanze = ui->cbxCharactor->currentIndex();
    if(0==xuanze)
    {
        bmpFile.xiaoboguolv();
        memcpy((void*)arrCharactor,bmpFile.m_pChara,sizeof(CharacterVector)*CHARACTER_LENGTH);
    }
    if(1==xuanze)
    {
        bmpFile.pca();
        memcpy((void*)arrCharactor,bmpFile.m_pChara,sizeof(CharacterVector)*CHARACTER_LENGTH);
    }
//    DataBase db;
    if( nullptr == m_pDB.data())
    {
        m_pDB.reset(new DataBase());
        if( ! m_pDB->createConnection())
        {
            ui->labShow->setText(tr("失败"));
            return;
        }
    }
    if( ! m_pDB->createConnection())
    {
        ui->labShow->setText(tr("失败"));
        return;
    }

    if( ! m_pDB->insertCharacotr(m_leftPictureName,arrCharactor,CHARACTER_LENGTH))
    {
        ui->labShow->setText(tr("失败"));
        return;
    }
    m_pDB->printCount(TABLE_REPOSITORY_INFO);
    m_pDB->printCount(TABLE_CHARACTOR_RECORD);

    ui->labShow->setText(tr("保存特征向量成功"));

    m_iIsComparing = false;
}

void MainWindow::slotAbout()
{
//    QMessageBox::information(
//                this,
//                tr("警告"),
//                tr("请确认源图片和目标图片都已选择!"),
//                QMessageBox::Ok);
//    QDialog * pDlg = new QDialog(this);
//    pDlg->setWindowTitle(tr("关于"));
    AboutDialog* pDlg = new AboutDialog(this);
    pDlg->show();
}

bool MainWindow::doGetFileName(QString &fileName)
{
    fileName = QFileDialog::getOpenFileName(
            this,
            tr("Open File"),
            "./../picture",
            tr("Images (*.png *.xpm *.jpg *.bmp)")
            );
    if( "" == fileName)
    {
        qWarning() << "Invalid file name";
        return false;
    }
    //check file if the rootPath/picture/.../xxx.bmp
    std::string strTemp = fileName.toStdString();
    std::string strRoot = m_rootPath.toStdString();
    std::string::size_type pos = strTemp.find(strRoot);
    if( std::string::npos == pos ||
            0 != pos )
    {
        qWarning() << "File " << fileName <<
                " Not in " << m_rootPath;
        fileName = "";
        return false;
    }
    std::string strFileName = strTemp.substr(
        strRoot.size()+1,strTemp.size() -
        strRoot.size() - 1);
    fileName = QString::fromStdString(strFileName);
    qDebug() << fileName;
    return true;
}

bool MainWindow::dbTest()
{
    return true;
}

void MainWindow::findMaxNum(CharacterVector *pCharactor, int maxSize)
{
    if( nullptr == pCharactor)
    {
        return;
    }
    //x
    CharacterVector* pTemp = pCharactor;
    long maxNum = pTemp->x;
    for(int index = 0; index<maxSize; ++index)
    {
        if( maxNum < pTemp->x)
        {
            maxNum = pTemp->x;
        }
        ++pTemp;
    }
    qDebug() << "Max x=" << maxNum;

    //y
    pTemp = pCharactor;
    maxNum = pTemp->y;
    for(int index = 0; index<maxSize; ++index)
    {
        if( maxNum < pTemp->y)
        {
            maxNum = pTemp->y;
        }
        ++pTemp;
    }
    qDebug() << "Max y=" << maxNum;

    return;
}

void MainWindow::stepShow()
{
    try
    {
        QPixmap pix;
        pix.load("temp.bmp");
        ui->labRightPictureShow->setPixmap(pix);
        ui->labRightPictureShow->show();
    }
    catch(QException& ex)
    {
        qWarning() << ex.what();
        return;
    }
}

void MainWindow::doStepShowAfterExec()
{
    int curStep = m_curStepAll;
    std::stringstream ss;
    if( STEP_FIND_INNER_INDEX == curStep )
    {
        CIRCLE circle = m_pBMPFileAll->m_innerCircle;
        ss << "坐标(" << circle.x <<
              "," << circle.y << ") 半径=" <<
              circle.r;
        ui->labRightPictureShow->hide();
        //show
        stepShow();
    }
    else if(STEP_FIND_OUTER_INDEX == curStep)
    {
        CIRCLE circle = m_pBMPFileAll->m_outerCircle;
        ss << "坐标(" << circle.x <<
              "," << circle.y << ") 半径=" <<
              circle.r;
        ui->labRightPictureShow->hide();
        //show
        stepShow();
    }
    else if(STEP_DLInsAlgorithm_INDEX == curStep)
    {
        ss << "归一处理成功";
        //show
        stepShow();
    }
    else if(STEP_LOGBin_INDEX == curStep)
    {
        ss << "拉普拉斯和二值化成功";
        //show
        stepShow();
    }
    else if(STEP_Morphological_INDEX == curStep)
    {
        ss << "形态学处理成功";
        //show
        stepShow();
    }
    else if(STEP_Get_Chara_INDEX == curStep)
    {
        ss << "获取特征向量成功";
        //show
//        stepShow();
    }
    else if(STEP_Save_Chara_INDEX == curStep)
    {
        ss << "存储特征向量成功";
        //show
//        stepShow();
    }
    else if(STEP_Recognise_INDEX == curStep)
    {
        ss << "识别成功";
        //show
//        stepShow();
    }

    ui->labShow->setText(QString::fromStdString(ss.str()));
}

void MainWindow::resetPreButton()
{
    m_curStepAll = 0;
    ui->btnStepInner->setEnabled(true);
    ui->btnStepOuter->setEnabled(true);
    ui->btnStepUnitize->setEnabled(true);
    ui->btnStepLOGBin->setEnabled(true);
    ui->btnStepMorph->setEnabled(true);
    ui->btnStepGetChararctor->setEnabled(true);
    ui->btnStepSaveChara->setEnabled(true);
    ui->btnStepRecognise->setEnabled(true);

    qDebug() << "Reset preducess button successful";
}

bool MainWindow::stepPreCheck(const int& stepIndex)
{
    if( ! m_iIsLeftSelected)
    {
        qWarning() << "Ensure source is selected right";
        QMessageBox::warning(
                    this,
                    tr("警告"),
                    tr("请确认源图片已选择!"),
                    QMessageBox::Ok);
        return false;
    }

    if(stepIndex != m_curStepAll)
    {
        qWarning() << "Do pre step first,index " <<
                      m_curStepAll << " had finished";
        QMessageBox::warning(
                    this,
                    tr("警告"),
                    tr("请先执行前一操作!"),
                    QMessageBox::Ok);
        return false;
    }
    return true;
}

void MainWindow::showAfterRecognise(const bmpFile_type &pBMPFile)
{
    //TODO:show picture
    RepositoryInfo_t repoInfo;
    pBMPFile->getRepoInfo(repoInfo);
    QString uri = m_rootPath + "/" +
            repoInfo.uri;
    try
    {
        QPixmap pix;
        QFile file(uri);
        if(! file.exists())
        {
            qWarning() << "Picture " << uri << " is not exists";
            std::stringstream ss;
            ss << "图片" << uri.toStdString().c_str() << "不在";
            ui->labRightPictureShow->setText(
                QString::fromStdString(ss.str()));
            return;
        }
        pix.load(uri);
        ui->labRightPictureShow->setPixmap(pix);
        ui->labRightPictureShow->show();
    }
    catch(QException& ex)
    {
        qWarning() << ex.what();
        ui->labShow->setText(ex.what());
        return;
    }
    ui->ledRightPath->setText(uri);

    double similarity = 0;
    pBMPFile->getSimilarity(similarity);
    std::stringstream ss;
    ss << "成功! 相似 " << similarity*100 << "%";

    ui->labShow->setText(QString::fromStdString(ss.str()));
    return;
}

void MainWindow::on_btnLeftOpenPicture_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    resetPreButton();
    m_iIsGetChara = false;
    m_iIsLeftSelected = false;
    ui->labShow->setText("");
    ui->btnGetChara->setEnabled(true);
    if( ! doGetFileName(m_leftPictureName))
    {
        m_iIsLeftSelected = false;
        return;
    }
    ui->ledLeftPath->setText(m_rootPath + "/" +m_leftPictureName);

    try
    {
        QPixmap pix;
        pix.load(m_rootPath + "/" +m_leftPictureName);
//        qDebug() << "colorCount:" << pix.colorCount();
        ui->labLeftPictureShow->setPixmap(pix);
        ui->labLeftPictureShow->show();
    }
    catch(QException& ex)
    {
        qWarning() << ex.what();
        m_iIsLeftSelected = false;
        return;
    }
    m_iIsLeftSelected = true;
    return;
}

void MainWindow::on_btnQuit_clicked()
{
    close();
}

void MainWindow::on_btnStepInner_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if( ! m_iIsLeftSelected)
    {
        qWarning() << "Ensure source is selected right";
        QMessageBox::warning(
                    this,
                    tr("警告"),
                    tr("请确认源图片已选择!"),
                    QMessageBox::Ok);
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText("Running . . .");

    m_curStepAll = 0;
    if( 0 == m_curStepAll)
    {
        m_pBMPFileAll.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    }

    if( !m_pBMPFileAll->stepExec(++m_curStepAll))
    {
        ui->labShow->setText(tr("失败"));
        resetPreButton();
        return;
    }

    doStepShowAfterExec();

    ui->btnStepInner->setEnabled(false);
    m_iIsComparing = false;
}

void MainWindow::on_btnStepOuter_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if(!stepPreCheck(STEP_FIND_INNER_INDEX))
    {
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText("Running . . .");

    if( 0 == m_curStepAll)
    {
        m_pBMPFileAll.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    }

    if( !m_pBMPFileAll->stepExec(++m_curStepAll))
    {
        ui->labShow->setText(tr("失败"));
        resetPreButton();
        return;
    }

    doStepShowAfterExec();

    ui->btnStepOuter->setEnabled(false);
    m_iIsComparing = false;
}

void MainWindow::on_btnStepUnitize_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if(!stepPreCheck(STEP_FIND_OUTER_INDEX))
    {
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText("Running . . .");

    if( 0 == m_curStepAll)
    {
        m_pBMPFileAll.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    }

    if( !m_pBMPFileAll->stepExec(++m_curStepAll))
    {
        ui->labShow->setText(tr("失败"));
        resetPreButton();
        return;
    }

    doStepShowAfterExec();

    ui->btnStepUnitize->setEnabled(false);
    m_iIsComparing = false;
}

void MainWindow::on_btnStepLOGBin_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if(!stepPreCheck(STEP_DLInsAlgorithm_INDEX))
    {
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText("Running . . .");

    if( 0 == m_curStepAll)
    {
        m_pBMPFileAll.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    }

    if( !m_pBMPFileAll->stepExec(++m_curStepAll))
    {
        ui->labShow->setText(tr("失败"));
        resetPreButton();
        return;
    }

    doStepShowAfterExec();

    ui->btnStepLOGBin->setEnabled(false);
    m_iIsComparing = false;
}

void MainWindow::on_btnStepMorph_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if(!stepPreCheck(STEP_LOGBin_INDEX))
    {
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText("Running . . .");

    if( 0 == m_curStepAll)
    {
        m_pBMPFileAll.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    }

    if( !m_pBMPFileAll->stepExec(++m_curStepAll))
    {
        ui->labShow->setText(tr("失败"));
        resetPreButton();
        return;
    }

    doStepShowAfterExec();

    ui->btnStepMorph->setEnabled(false);
    m_iIsComparing = false;
}

void MainWindow::on_btnStepGetChararctor_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if(!stepPreCheck(STEP_Morphological_INDEX))
    {
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText("Running . . .");

    if( 0 == m_curStepAll)
    {
        m_pBMPFileAll.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    }
    m_pBMPFileAll->setGetAlgorithm(
            ui->cbxStepCharactor->currentIndex()+1);
    if( !m_pBMPFileAll->stepExec(++m_curStepAll))
    {
        ui->labShow->setText(tr("失败"));
        resetPreButton();
        return;
    }

    doStepShowAfterExec();

    ui->btnStepGetChararctor->setEnabled(false);
    m_iIsComparing = false;
}

void MainWindow::on_btnStepSaveChara_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if(!stepPreCheck(STEP_Get_Chara_INDEX))
    {
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText("Running . . .");

    if( 0 == m_curStepAll)
    {
        m_pBMPFileAll.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    }
    m_pBMPFileAll->setLastName(m_leftPictureName);
    if( !m_pBMPFileAll->stepExec(++m_curStepAll))
    {
        ui->labShow->setText(tr("失败"));
        resetPreButton();
        return;
    }

    doStepShowAfterExec();

    ui->btnStepSaveChara->setEnabled(false);
    m_iIsComparing = false;
}

void MainWindow::on_btnStepRecognise_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }

    //if not save charactor
    if( STEP_Get_Chara_INDEX == m_curStepAll )
    {
        qDebug() << "Recognise without save charactor";
        ++m_curStepAll;
        ui->btnStepSaveChara->setEnabled(false);
    }

    if(!stepPreCheck(STEP_Save_Chara_INDEX))
    {
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText(tr("识别 . . ."));

    if( 0 == m_curStepAll)
    {
        m_pBMPFileAll.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    }
    m_pBMPFileAll->setRecogniseAlgorithm(
            ui->cbxStepRecognise->currentIndex()+1);
    if( !m_pBMPFileAll->stepExec(++m_curStepAll))
    {
        ui->labShow->setText(tr("失败"));
        resetPreButton();
        return;
    }

    showAfterRecognise(m_pBMPFileAll);

    resetPreButton();

    m_iIsComparing = false;
}

void MainWindow::on_btnGetChara_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if( ! m_iIsLeftSelected)
    {
        qWarning() << "Ensure source is selected right";
        QMessageBox::warning(
                    this,
                    tr("警告"),
                    tr("请确认源图片已选择!"),
                    QMessageBox::Ok);
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText(tr("识别 . . ."));

    m_pBMPFile.reset(new BMPFile(m_rootPath + "/" +m_leftPictureName));
    //set config
    m_pBMPFile->setGetAlgorithm(
        ui->cbxCharactor->currentIndex() + 1);
    m_pBMPFile->setLastName(m_leftPictureName);

    for(int index = 0; index<STEP_Get_Chara_INDEX;)
    {
        if( !m_pBMPFile->stepExec(++index))
        {
            ui->labShow->setText(tr("失败"));
            return;
        }
    }

    //TODO:show charactor point picture

    ui->labShow->setText(tr("提取成功"));
    ui->btnGetChara->setEnabled(false);
    m_iIsComparing = false;
    m_iIsGetChara = true;
}

void MainWindow::on_btnRecognise_clicked()
{
    if(m_iIsComparing)
    {
        return;
    }
    if( ! m_iIsLeftSelected)
    {
        qWarning() << "Ensure source is selected right";
        QMessageBox::warning(
                    this,
                    tr("警告"),
                    tr("请确认源图片已选择!"),
                    QMessageBox::Ok);
        return;
    }
    if( ! m_iIsGetChara)
    {
        qWarning() << "Get charactor first";
        QMessageBox::warning(
                    this,
                    tr("警告"),
                    tr("请先提取特征!"),
                    QMessageBox::Ok);
        return;
    }
    if( nullptr == m_pBMPFile.data())
    {
        qWarning() << "nullptr";
        return;
    }

    m_iIsComparing = true;
    ui->labShow->setText(tr("识别 . . ."));

    m_pBMPFile->setRecogniseAlgorithm(
        ui->cbxRecognise->currentIndex() + 1);
    if( !m_pBMPFile->stepExec(STEP_Recognise_INDEX))
    {
        ui->labShow->setText(tr("失败"));
        return;
    }

    showAfterRecognise(m_pBMPFile);

    ui->btnGetChara->setEnabled(true);
    m_iIsComparing = false;
    m_iIsGetChara = false;
}
